﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;
using System.Windows.Input;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace NuckChorris
{
    public partial class Classname : CombatRoutine
    {
        public string LastSpell = "";
        public string LastLog = "";
        public string Jab = "Jab"; //1
		public string Roll = "Roll"; //1
		public string TigerPalm = "Tiger Palm"; //3 1chi
		public string BlackoutKick = "Blackout Kick"; //7 2chi
		public string Provoke = "Provoke"; //14
		public string Resuscitate = "Resuscitate"; //18
		public string Detox = "Detox"; //20
		public string ZenPilgrimage = "Zen Pilgrimage"; //20
		public string LegacyEmperor = "Legacy of the Emperor"; //22
		public string TouchDead = "Touch of Death"; // 22 3chi
		public string FortBrew = "Fortifying Brew"; //24
		public string ExpelHarm = "Expel Harm"; //26
		public string Disable = "Disable"; //28
		public string SpearHandStrike = "Spear Hand Strike"; // 32
		public string Paralysis = "Paralysis"; // 44
		public string SpinningCraneKick = "Spinning Crane Kick"; // 46
		public string CracklingJadeLighting = "Crackling Jade Lightning";// 54
		public string HealingSphere = "Healing Sphere"; // 64
		public string PathBlosseom = "Path of Blossoms"; //64
		public string GrappleWeapon = "Grapple Weapon"; // 68
		public string Transcendence = "Transcendence"; // 87
		public string TranscendenceTrans = "Transcendence: Transfer"; // 87
		public string FistofFury = "Fists of Fury"; // 10 3chi
		public string ZenMeditation = "Zen Meditation"; // 82
		public string LehacyOfTheWhiteTiger = "Legacy of the White Tiger";
		public string TouchOfkarma = "Touch of Karma";
		public string EnergizingBrew = "Energizing Brew";
		public string Xuen = "Invoke Xuen, the White Tiger"; // talent
		public string LegSweep = "Leg Sweep"; // talent
		public string DiffuseMagic = "Diffuse Magic"; // talent
		public string DampenHarm = "Dampen Harm"; // talent
		public string RushingJadeWind = "Rushing Jade Wind"; // talent
		public string ChiTorpedo = "Chi Torpedo"; // talent
		public string ChargingOxWave = "Charging Ox Wave"; // talent
		public string TigersLust = "Tiger's Lust"; // talent
		public string RisingSunKick = "Rising Sun Kick"; // 55 2chi
		
		public string CBTigerPalm = "Combo Breaker: Tiger Palm";
		public string CBBlackoutKick = "Combo Breaker: Blackout Kick";
		public string DeathNote = "Death Note";
        public string TigerPower = "Tiger Power";
		public string TigerEyeBrew = "Tigereye Brew";
		public string ChiBrew = "Chi Brew"; // talent
		public string QuakingPalm = "Quacking Palm";
		public string ChiBurst = "Chi Burst"; //talent 2 chi
        public string ChiWave = "Chi Wave"; //talent 2 chi
        public int teller = 1;

        private bool Rolling
        {
            get
            {
                if (Me.CurrentTarget != null
                    && Me.CurrentTarget.InLineOfSight
                    && GetSpellCooldown(Roll).TotalSeconds == 0)
                {
                    return true;
                }
                return false;
            }
        }
        public string PullSpell
        {
            get 
            {
                if (SpellManager.HasSpell(Provoke)
                    && GetSpellCooldown(Provoke).TotalSeconds == 0)
                {
                    return Provoke;
                }
                if (SpellManager.HasSpell(CracklingJadeLighting)
                    && GetSpellCooldown(CracklingJadeLighting).TotalSeconds == 0
                    && GetSpellCooldown(Provoke).TotalSeconds > 0
                    && LastSpell != Provoke)
                {
                    return CracklingJadeLighting;
                }
                if (!SpellManager.HasSpell(Provoke)
                    && !SpellManager.HasSpell(CracklingJadeLighting))
                {
                    return Jab;
                }
                return null;
            }
        }

        public bool MeIsAlive
        {
            get
            {
                if (Me.IsDead || Me.IsGhost)
                {
                    return false;
                }
                return true;
            }
        }
        public bool UseSpells
        {
            get
            {
                if (Me.Mounted
                    || Me.HasAura("Drink")
                    || Me.HasAura("Food")
                    || Me.HasAura("First Aid"))
                {
                    return false;
                }
                return true;
            }
        }
        public void CastSpell(string spell, int logColor)
        {
            if (SpellManager.CanCast(spell))
            {
                SpellManager.Cast(spell);
                LogMsg(spell, logColor);
                LastSpell = spell;
            }
        }
		public void CastRemote(string spell, int logColor)
        {
            if (SpellManager.CanCast(spell))
            {
                SpellManager.Cast(spell);
                SpellManager.ClickRemoteLocation(StyxWoW.Me.CurrentTarget.Location);
                LogMsg(spell, logColor);
                LastSpell = spell;
            }
        }
        public void CastBuff(string spell, int logColor)
        {
            if (UseSpells
                && SpellManager.CanCast(spell))
            { 
                SpellManager.Cast(spell, StyxWoW.Me);
                StyxWoW.SleepForLagDuration();
                LogMsg(spell, logColor);
                LastSpell = spell; 
            }
            
        }
        public bool UseSkill(string spell)
        {
            if (Me.CurrentTarget != null
                && SpellManager.HasSpell(spell)
                && Me.CurrentTarget.InLineOfSight
                && Me.CurrentTarget.IsWithinMeleeRange
                && !Me.IsChanneling)
            {
                return true;
            }
            return false;
        }
        #region MyAuraTimeLeft

        public double MyAuraTimeLeft(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double MyAuraTimeLeft(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion


        #region ensuretargets
        private WoWUnit curTar;

        #region pvp
        private bool PVPLogic = true;
        private WoWUnit PlayerAttackingMe
        {
            get
            {
                WoWUnit newTarget = (from o in ObjectManager.ObjectList
                                     where o is WoWUnit
                                     let unit = o.ToUnit()
                                     where
                                         unit.Distance < 40
                                         && unit.IsTargetingMeOrPet
                                         && unit.Combat
                                         && unit.PvpFlagged
                                         && unit.IsHostile
                                         && unit.IsPlayer
                                         && unit.IsAlive
                                         && !unit.IsFriendly
                                         && !unit.IsPet
                                         && !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                                     orderby unit.BaseHealth ascending
                                     select unit
                                 ).FirstOrDefault();
                if (newTarget != null)
                    return newTarget;

                return null;
            }
        }
        #endregion

        public static void EnsureTarget()
        {
            if (StyxWoW.Me.IsInInstance &&
                TankManager.TargetingTimer.IsFinished && StyxWoW.Me.Combat && TankManager.Instance.FirstUnit != null &&
                (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget != TankManager.Instance.FirstUnit))
            {
                Logging.Write("Targeting first unit of TankTargeting");
                TankManager.Instance.FirstUnit.Target();
                TankManager.TargetingTimer.Reset();
            }

            WoWObject ctx = GatherTarget();
            if (ctx != null)
            {
                Logging.Write("Current target is not the best target. Switching to " + ctx + "!");
                ((WoWUnit)ctx).Target();
            }

            if (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget.IsDead)
            {
                ctx = GatherTarget2();
                if (ctx != null)
                {
                    Logging.Write("Currect target is invalid. Switching to " + ctx + "!");
                    ((WoWUnit)ctx).Target();
                }
            }
        }

        private static WoWObject GatherTarget2()
        {
            // If we have a RaF leader, then use its target.
            var rafLeader = RaFHelper.Leader;
            if (rafLeader != null && rafLeader.IsValid && !rafLeader.IsMe && rafLeader.Combat &&
                rafLeader.CurrentTarget != null && rafLeader.CurrentTarget.IsAlive && !Blacklist.Contains(rafLeader.CurrentTarget))
            {
                return rafLeader;
            }

            // Check bot poi.
            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var unit = BotPoi.Current.AsObject as WoWUnit;

                if (unit != null && unit.IsAlive && !unit.IsMe && !Blacklist.Contains(unit))
                {
                    return unit;
                }
            }

            // Does the target list have anything in it? And is the unit in combat?
            // Make sure we only check target combat, if we're NOT in a BG. (Inside BGs, all targets are valid!!)
            var firstUnit = Targeting.Instance.FirstUnit;
            if (firstUnit != null && firstUnit.IsAlive && !firstUnit.IsMe && firstUnit.Combat &&
                !Blacklist.Contains(firstUnit))
            {
                return firstUnit;
            }

            // Cache this query, since we'll be using it for 2 checks. No need to re-query it.
            var agroMob =
                ObjectManager.GetObjectsOfType<WoWUnit>(false, false).
                    Where(p => !Blacklist.Contains(p) && p.IsHostile && !p.IsOnTransport && !p.IsDead &&
                                !p.Mounted && p.DistanceSqr <= 70 * 70 && p.Combat).
                    OrderBy(u => u.DistanceSqr).
                    FirstOrDefault();

            if (agroMob != null)
            {
                // Return the closest one to us
                return agroMob;
            }

            // And there's nothing left, so just return null, kthx.
            return null;
        }

        private static WoWObject GatherTarget()
        {
            // No target switching for tanks. They check for their own stuff above.
            if (StyxWoW.Me.IsInInstance)
                return null;
            // Go below if current target is null or dead. We have other checks to deal with that
            if (StyxWoW.Me.CurrentTarget == null || StyxWoW.Me.CurrentTarget.IsDead)
                return null;
            // If the current target is in combat or has aggro towards us, it should be a valid target.
            if (StyxWoW.Me.CurrentTarget != null && (StyxWoW.Me.CurrentTarget.Combat || StyxWoW.Me.CurrentTarget.Aggro))
                return null;
            if (BotPoi.Current.Type == PoiType.Kill)
            {
                var obj = BotPoi.Current.AsObject;

                if (obj != null)
                {
                    if (StyxWoW.Me.CurrentTarget != obj)
                        return obj;
                }
            }
            // Make sure we have the proper target from Targeting. 
            // The Botbase should give us the best target in targeting.
            var firstUnit = Targeting.Instance.FirstUnit;

            if (firstUnit != null)
            {
                if (StyxWoW.Me.CurrentTarget != firstUnit)
                    return firstUnit;
            }
            return null;
        }

        private static WoWPoint CalculatePointBehindTarget()
        {
            return
                StyxWoW.Me.CurrentTarget.Location.RayCast(
                    StyxWoW.Me.CurrentTarget.Rotation + WoWMathHelper.DegreesToRadians(150), MeleeRange - 2f);
        }
        #endregion ensuretargets
        #region logs
        public static void LogMsg(string msg, int kleurtje)
        {
            Color kleur = Colors.Yellow;
            switch (kleurtje)
            {
                case 0:
                    kleur = Colors.Orange;
                    break;
                case 1:
                    kleur = Colors.PaleGreen;
                    break;
                case 2:
                    kleur = Colors.BlanchedAlmond;
                    break;
                case 3:
                    kleur = Colors.Yellow;
                    break;
                case 4:
                    kleur = Colors.Red;
                    break;
                case 5:
                    kleur = Colors.Crimson;
                    break;
            }
            Logging.Write(kleur, msg);
        }
        #endregion logs
        #region Trinkets
        public void UseTrinket1()
        {
            var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
            if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
            {
                firstTrinket.Use();
                LogMsg("Using 1st trinket", 2);
            }
        }
        public void Usetrinket2()
        {
            var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;
            if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
            {
                secondTrinket.Use();
                LogMsg("Using 2nd trinket", 2);
            }
        }
        public void UseEngiGloves()
        {
            var engiGloves = StyxWoW.Me.Inventory.Equipped.Hands;
            if (engiGloves != null && CanUseEquippedItem(engiGloves))
            {
                engiGloves.Use();
                LogMsg("Using Engineer Gloves", 2);
            }
        }
        public void UseEngiBelt()
        {
            var engiBelt = StyxWoW.Me.Inventory.Equipped.Waist;

            if (engiBelt != null && CanUseEquippedItem(engiBelt))
            {
                engiBelt.Use();
                LogMsg("Using Engineer Belt", 2);
            }
        }
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }
        #endregion Trinkets
        public bool CanUseTrinket1
        {
            get
            {
                if (NuckChorrisSettings.myPrefs.Mtrinket1 == 0)
                {
                    return false;
                }

                var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
                if (firstTrinket != null && !CanUseEquippedItem(firstTrinket))
                {
                    return false;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket1 == 1
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket1 == 2
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket1 == 3)
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket1 == 4
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks)
                {
                    return true;
                }
                return false;
            }
        }
        public bool CanUseTrinket2
        {
            get
            {
                if (NuckChorrisSettings.myPrefs.Mtrinket2 == 0)
                {
                    return false;
                }
                var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;
                if (secondTrinket != null && !CanUseEquippedItem(secondTrinket))
                {
                    return false;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket2 == 1
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket2 == 2
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket2 == 3)
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.Mtrinket2 == 4
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks)
                {
                    return true;
                }
                return false;
            }
        }
        public bool CanUseEngiGloves
        {
            get
            {
                if (NuckChorrisSettings.myPrefs.MEngiGloves == 0)
                {
                    return false;
                }

                var engiGloves = StyxWoW.Me.Inventory.Equipped.Waist;
                if (engiGloves != null && !CanUseEquippedItem(engiGloves))
                {
                    return false;
                }
                if (NuckChorrisSettings.myPrefs.MEngiGloves == 1
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.MEngiGloves == 2
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks
                    && IsBoss())
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.MEngiGloves == 3)
                {
                    return true;
                }
                if (NuckChorrisSettings.myPrefs.MEngiGloves == 4
                    && Me.ActiveAuras.ContainsKey(TigerEyeBrew)
                    && Me.GetAuraByName(TigerEyeBrew).StackCount >= NuckChorrisSettings.myPrefs.TEBStacks)
                {
                    return true;
                }
                return false;
            }
        }

        #region pause
        public bool Paused = false;

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        private void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (NuckChorrisSettings.myPrefs.PauseKeys == NuckChorrisSettings.Keypress.None)
            {
                return;
            }

            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == NuckChorrisSettings.myPrefs.PauseKeys.ToString())
                {
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("NuckChorris PAUSED, press {0} in WOW to continue",
                                     NuckChorrisSettings.myPrefs.PauseKeys.ToString());
                        if (NuckChorrisSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"NuckChorris PAUSED\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("NuckChorris Running....");
                        if (NuckChorrisSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"NuckChorris Resumed\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause
        public void UseHealingSpheres()
        {
            if (Me.CurrentTarget != null
                && Me.Combat
                && SpellManager.HasSpell(HealingSphere))
            {
                while (Me.HealthPercent <= NuckChorrisSettings.myPrefs.HealingSpheresPercent
                    && Me.EnergyPercent >= 40)
                {
                    Lua.DoString("SpellStopTargeting()");
                    Lua.DoString("CastSpellByName('Healing Sphere');");
                    {
                        SpellManager.ClickRemoteLocation(Me.Location);
                        StyxWoW.SleepForLagDuration();
                    }
                }
            }
            MouseClick(Me.Location, MouseAction.RightClick);
            LogMsg(HealingSphere, 2);
            return;
        }

        public void MouseClick(WoWPoint location, MouseAction button) { return; }  
        
    }
}
